#include "CatchBehaviour.h"
#include "../../CommonFunctions.h"

/*
 *	Brankar chyti loptu, najnizsie spravanie chytania.
 *  Jedna sa len o poslanie prikazu na server
 */
void CatchBehaviour::Behave()
{
	float uhol = CalcDir(world->ball->pos - world->me->pos, world->me->GetAbsDir()).GetDeg();
	commandGenerator->Catch(uhol);
	DATA_STORAGE.goalieCatch.goalieCatchBan = world->params->server->catch_ban_cycle; 
}

bool CatchBehaviour::CanCatchBall()
{
	return CanCatchBall(1.0f, world->me->pos,world->ball->pos, 0);
}

bool CatchBehaviour::CanCatchBall(float catch_coef, const Point& myFuturePos, const Point& ballFuturePos, int cycles)
{
	// Iba brankar moze chytat loptu
	if(DATA_STORAGE.playerRole != PR_Goalie)
		return false;

	// V tomto mode sa nemoze chytat
	if(world->state->GetPlayMode() != PM_PlayOn)
		return false;

	// Lopta je daleko
	if((myFuturePos - ballFuturePos).GetLength() >= catch_coef * world->params->server->catchable_area_l)
		return false;

	// Pred chvilou chytal
	if(DATA_STORAGE.goalieCatch.goalieCatchBan > cycles)
		return false;

	// Je mimo penaltoveho uzemia
	if(fabsf(ballFuturePos.GetY()) >= 20.16f)
		return false;
	if(ballFuturePos.GetX() >= -36.f)
		return false;

	return true;
}

/*
 * Brankar sa snazi zachytit loptu pri hrani.
 * Snazi sa pocas dvoch cyklov zachytit loptu.
 *
 * @return true ak vie brankar bezpece/nebezpecne zachytit loptu, ak nie false
 */
bool CatchBehaviour::TryCatchBall()
{
	if(Intercept2Cycles(0.85f))
	{
		//bezpecne chytenie lopty
		return true;
	}
	if(((world->ball->GetAge() == 0) || DATA_STORAGE.BallHeadingOnOurGoal()) && Intercept2Cycles(0.95f))
	{
		//nebezpecne chytenie lopty
		return true;
	}
	return false;
}


/*
 * Snazi sa zachytit loptu pocas tohto alebo nasledujuceho cyklu.
 * Ak moze zachytit loptu v tomto cykle, chyti ju. Ak v dalsom, presunie
 * sa k nej prikazom dash a potom ju zachyti. Ak sa neda, snazi sa ju
 * pomocou prikazu dash alebo turn dostat k nej.
 *
 * @param catch_coef  nakolko riskuje pri snahe zachytit loptu
 *
 * @return funkcia vrati true, ak brankar vie bezpecne chytit loptu pocas 0 - 1 cyklus
 */
bool CatchBehaviour::Intercept2Cycles(float catch_coef)
{
	//*****************************0 cyklov*************************************
	if(CanCatchBall(catch_coef, world->me->pos, world->ball->pos, 0))
	{
		G_TXTN("  CatchBall %.2f - 0 CYCLES", catch_coef);
		Behave();
		return true;
	}
	Ball tmpBall1(*world->ball);
	tmpBall1.Step();
	Ball tmpBall2(*world->ball);
	tmpBall2.Step();
	tmpBall2.Step();

	//******************************1 cyklus************************************
	Point best_point;
	float best_dash = GetDashBehaviour()->GetBestDash(tmpBall1.pos, *world->me, best_point, 10.f);
	if(best_dash != NO_BEST_DASH)
	{
		if(CanCatchBall(catch_coef, best_point, tmpBall1.pos, 1))
		{
			G_TXTN("  CatchBall %.2f - 1 CYCLE; DASH %.2f", catch_coef, best_dash);
			GetDashBehaviour()->Behave(best_dash);
			return true;
		}
	}

	//******************************2 cykly*************************************
	//DASH - DASH kombinacia
	for(float f = world->params->server->minpower; f <= world->params->server->maxpower; f += 50.f)
	{
		Myself ja_1cyklus = GetRunToPositionBehaviour()->AfterDash(*world->me, f);
		best_dash = GetDashBehaviour()->GetBestDash(tmpBall2.pos, ja_1cyklus, best_point, 10.f);
		if(best_dash != NO_BEST_DASH)
		{
			if(CanCatchBall(catch_coef, best_point, tmpBall2.pos, 2))
			{
				G_TXTN("  CatchBall %.2f - 2 CYCLES; DASH %.2f; DASH %.2f", catch_coef, f, best_dash);
				GetDashBehaviour()->Behave(f);
				return true;
			}
		}
	}

	//TURN - DASH
	for(float m = world->params->server->minmoment; m <= world->params->server->maxmoment; m += 30.f)
	{
		Myself ja_1cyklus = GetTurnToBehaviour()->AfterTurn(*world->me, m);
		best_dash = GetDashBehaviour()->GetBestDash(tmpBall2.pos, ja_1cyklus, best_point, 10.f);
		if(best_dash != NO_BEST_DASH)
		{
			if(CanCatchBall(catch_coef, best_point, tmpBall2.pos, 2))
			{
				G_TXTN("  CatchBall %.2f - 2 CYCLES; TURN %.2f; DASH %.2f", catch_coef, m, best_dash);
				GetTurnToBehaviour()->GoalieTurn(m);
				return true;
			}
		}
	}
	return false;
}
